﻿using System;
using Unity.Mathematics;
using UnityEngine;

namespace Jinndev {
    
    public struct Float2 : IEquatable<Float2> {

        public static readonly Float2 zero = new Float2(0);
        public static readonly Float2 one = new Float2(1);
        public static readonly Float2 half = new Float2(0.5f);

        public static readonly Float2 up = new Float2(0, 1);
        public static readonly Float2 left = new Float2(-1, 0);
        public static readonly Float2 right = new Float2(1, 0);
        public static readonly Float2 down = new Float2(0, -1);

        public static readonly Float2 upLeft = new Float2(-0.5f, 0.5f);
        public static readonly Float2 upRight = new Float2(0.5f, 0.5f);
        public static readonly Float2 downLeft = new Float2(-0.5f, -0.5f);
        public static readonly Float2 downRight = new Float2(0.5f, -0.5f);

        public float x;
        public float y;

        public Float2(float x, float y) {
            this.x = x;
            this.y = y;
        }

        public Float2(float value) {
            x = value;
            y = value;
        }

        public Float2(Int2 value) {
            x = value.x;
            y = value.y;
        }

        public Float2(float[] array) {
            x = array.Length >= 1 ? array[0] : 0;
            y = array.Length >= 2 ? array[1] : 0;
        }

        public float[] ToArray() {
            return new float[] { x, y };
        }

        public static implicit operator Float2(float2 v) {
            return new Float2(v.x, v.y);
        }

        public static implicit operator float2(Float2 v) {
            return new float2(v.x, v.y);
        }

        public static implicit operator Float2(Vector2 v) {
            return new Float2(v.x, v.y);
        }

        public static implicit operator Vector2(Float2 v) {
            return new Vector2(v.x, v.y);
        }

        public static bool operator ==(Float2 lhs, Float2 rhs) {
            return lhs.Equals(rhs);
        }

        public static bool operator !=(Float2 lhs, Float2 rhs) {
            return !lhs.Equals(rhs);
        }

        public static Float2 operator +(Float2 a, Float2 b) {
            return new Float2(a.x + b.x, a.y + b.y);
        }

        public static Float2 operator -(Float2 a, Float2 b) {
            return new Float2(a.x - b.x, a.y - b.y);
        }

        public static Float2 operator *(Float2 a, Float2 b) {
            return new Float2(a.x * b.x, a.y * b.y);
        }

        public static Float2 operator /(Float2 a, Float2 b) {
            return new Float2(a.x / b.x, a.y / b.y);
        }

        #region Float2 float
        public static Float2 operator +(Float2 a, float b) {
            return new Float2(a.x + b, a.y + b);
        }
        public static Float2 operator +(float a, Float2 b) {
            return new Float2(a + b.x, a + b.y);
        }
        
        public static Float2 operator -(Float2 a, float b) {
            return new Float2(a.x - b, a.y - b);
        }
        public static Float2 operator -(float a, Float2 b) {
            return new Float2(a - b.x, a - b.y);
        }
        
        public static Float2 operator *(Float2 a, float b) {
            return new Float2(a.x * b, a.y * b);
        }
        public static Float2 operator *(float a, Float2 b) {
            return new Float2(a * b.x, a * b.y);
        }

        public static Float2 operator /(Float2 a, float b) {
            return new Float2(a.x / b, a.y / b);
        }
        public static Float2 operator /(float a, Float2 b) {
            return new Float2(a / b.x, a / b.y);
        }
        #endregion

        #region Float2 float2
        public static Float2 operator +(Float2 a, float2 b) {
            return new Float2(a.x + b.x, a.y + b.y);
        }
        public static float2 operator +(float2 a, Float2 b) {
            return new float2(a.x + b.x, a.y + b.y);
        }

        public static Float2 operator -(Float2 a, float2 b) {
            return new Float2(a.x - b.x, a.y - b.y);
        }
        public static float2 operator -(float2 a, Float2 b) {
            return new float2(a.x - b.x, a.y - b.y);
        }

        public static Float2 operator *(Float2 a, float2 b) {
            return new Float2(a.x * b.x, a.y * b.y);
        }
        public static float2 operator *(float2 a, Float2 b) {
            return new float2(a.x * b.x, a.y * b.y);
        }

        public static Float2 operator /(Float2 a, float2 b) {
            return new Float2(a.x / b.x, a.y / b.y);
        }
        public static float2 operator /(float2 a, Float2 b) {
            return new float2(a.x / b.x, a.y / b.y);
        }
        #endregion

        #region Float2 float3
        public static float3 operator +(Float2 a, float3 b) {
            return new float3(a.x + b.x, a.y + b.y, b.z);
        }
        public static float3 operator +(float3 a, Float2 b) {
            return new float3(a.x + b.x, a.y + b.y, a.z);
        }

        public static float3 operator -(Float2 a, float3 b) {
            return new float3(a.x - b.x, a.y - b.y, -b.z);
        }
        public static float3 operator -(float3 a, Float2 b) {
            return new float3(a.x - b.x, a.y - b.y, a.z);
        }

        public static float3 operator *(Float2 a, float3 b) {
            return new float3(a.x * b.x, a.y * b.y, b.z);
        }
        public static float3 operator *(float3 a, Float2 b) {
            return new float3(a.x * b.x, a.y * b.y, a.z);
        }

        public static float3 operator /(Float2 a, float3 b) {
            return new float3(a.x / b.x, a.y / b.y, b.z);
        }
        public static float3 operator /(float3 a, Float2 b) {
            return new float3(a.x / b.x, a.y / b.y, a.z);
        }
        #endregion

        #region Float2 int2
        public static Float2 operator +(Float2 a, int2 b) {
            return new Float2(a.x + b.x, a.y + b.y);
        }
        public static Float2 operator +(int2 a, Float2 b) {
            return new Float2(a.x + b.x, a.y + b.y);
        }

        public static Float2 operator -(Float2 a, int2 b) {
            return new Float2(a.x - b.x, a.y - b.y);
        }
        public static Float2 operator -(int2 a, Float2 b) {
            return new Float2(a.x - b.x, a.y - b.y);
        }

        public static Float2 operator *(Float2 a, int2 b) {
            return new Float2(a.x * b.x, a.y * b.y);
        }
        public static Float2 operator *(int2 a, Float2 b) {
            return new Float2(a.x * b.x, a.y * b.y);
        }

        public static Float2 operator /(Float2 a, int2 b) {
            return new Float2(a.x / b.x, a.y / b.y);
        }
        public static Float2 operator /(int2 a, Float2 b) {
            return new Float2(a.x / b.x, a.y / b.y);
        }
        #endregion

        public bool Equals(Float2 other) {
            return other.x == x && other.y == y;
        }

        public override bool Equals(object obj) {
            return obj is Float2 && Equals((Float2)obj);
        }

        public override int GetHashCode() {
            return (int)math.hash(new Float2(x, y));
        }

        public override string ToString() {
            return $"Float2({x}, {y})";
        }
        //public static Float2 operator *(Float2 lhs, Vector2 rhs) {
        //    return new Float2(lhs.x * rhs.x, lhs.y * rhs.y);
        //}

    }

}

